﻿#include "widget.h"

GLuint VBO[2], VAO[2] ,EBO[2];
const char *vertexShaderSource =
        "#version 330 core\n"
        "layout(location = 0) in vec3 aPos;\n"
        "layout (location = 1) in vec3 aColor;\n"
        "layout (location = 2) in vec2 aTexCoord;\n"
        "out vec3 ourColor;\n"
        "out vec2 TexCoord;\n"
        "void main(){\n"
        "   gl_Position = vec4(aPos, 1.0);\n"
        "   ourColor = aColor;\n"
        "   TexCoord = vec2(aTexCoord.x, aTexCoord.y);\n"
        "}\n\0";
const char *fragmentShaderSource =
        "#version 330 core\n"
        "in vec3 ourColor;\n"
        "in vec2 TexCoord;\n"
        "out vec4 FragColor;\n"
        "uniform sampler2D texture1;\n"
        "uniform sampler2D texture2;\n"
        "void main(){\n"
        "   FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.1)* vec4(ourColor, 1.0);\n"
        "}\n\0";

Triangle::Triangle(QWidget *parent){
    coloursource =0;
}

Triangle::~Triangle(){

}

void Triangle::initializeGL(){



    //着色器部分
    core = QOpenGLContext::currentContext()->versionFunctions<QOpenGLFunctions_3_3_Core>();//获取上下文
    int vertexShader = core->glCreateShader(GL_VERTEX_SHADER);
    core->glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
    core->glCompileShader(vertexShader);
    // check for shader compile errors
    int success;
    char infoLog[512];
    core->glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        core->glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << endl;
    }
    // fragment shader
    int fragmentShader = core->glCreateShader(GL_FRAGMENT_SHADER);

    core->glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
    core->glCompileShader(fragmentShader);
    // check for shader compile errors
    core->glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        core->glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << endl;
    }

    shaderProgram = core->glCreateProgram();
    core->glAttachShader(shaderProgram, vertexShader);
    core->glAttachShader(shaderProgram, fragmentShader);
    core->glLinkProgram(shaderProgram);
    // check for linking errors
    core->glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if (!success) {
        core->glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        qDebug() << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << endl;
    }
    core->glDeleteShader(vertexShader);
    core->glDeleteShader(fragmentShader);

    //VAO，VBO数据部分
    float vertices[] = {
    //     ---- 位置 ----       ---- 颜色 ----     - 纹理坐标 -
         0.5f,  0.5f, 0.0f,   1.0f, 0.0f, 0.0f,   1.0f, 0.0f,   // 右上
         0.5f, -0.5f, 0.0f,   0.0f, 1.0f, 0.0f,   1.0f, 1.0f,   // 右下
        -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, 1.0f,   0.0f, 1.0f,   // 左下
        -0.5f,  0.5f, 0.0f,   1.0f, 1.0f, 0.0f,   0.0f, 0.0f    // 左上
    };
    unsigned int indices[] = {
        0, 1, 3, // first triangle
        1, 2, 3  // second triangle
    };

    core->glGenVertexArrays(1, VAO);//两个参数，第一个为需要创建的缓存数量。第二个为用于存储单一ID或多个ID的GLuint变量或数组的地址
    core->glGenBuffers(1, VBO);
    core->glGenBuffers(1, EBO);

    core->glBindVertexArray(VAO[0]);

    core->glBindBuffer(GL_ARRAY_BUFFER, VBO[0]);
    core->glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    core->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO[0]);
    core->glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);

    // position attribute
    core->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    core->glEnableVertexAttribArray(0);
    // color attribute
    core->glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    core->glEnableVertexAttribArray(1);
    // texture coord attribute
    core->glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    core->glEnableVertexAttribArray(2);

    core->glBindBuffer(GL_ARRAY_BUFFER, 0);
    core->glBindVertexArray(0);


    core->glGenTextures(1, &texture1);
    core->glBindTexture(GL_TEXTURE_2D, texture1);
    // 为当前绑定的纹理对象设置环绕、过滤方式
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 加载并生成纹理
    cv::Mat image = cv::imread("F:\\QTproject\\tuchuan_202105_qt\\111.jpg");
    cv::resize(image,image,cv::Size(640,512));
    GLchar *data = (GLchar*)image.data;
    if (data)
    {
        core->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
        core->glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }

    core->glGenTextures(1, &texture2);
    core->glBindTexture(GL_TEXTURE_2D, texture2);
    // 为当前绑定的纹理对象设置环绕、过滤方式
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    core->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // 加载并生成纹理
    image = cv::imread("F:\\QTproject\\tuchuan_202105_qt\\123.jpg");
    cv::resize(image,image,cv::Size(640,512));
    data = (GLchar*)image.data;
    if (data)
    {
        core->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
        core->glGenerateMipmap(GL_TEXTURE_2D);
    }
    else
    {
        std::cout << "Failed to load texture" << std::endl;
    }

    core->glUseProgram(shaderProgram);
    // either set it manually like so:
    core->glUniform1i(core->glGetUniformLocation(shaderProgram, "texture1"), 0);
    core->glUniform1i(core->glGetUniformLocation(shaderProgram, "texture1"), 1);

}

void Triangle::resizeGL(int w, int h){
    core->glViewport(0, 0, w, h);
}

void Triangle::paintGL(){
    core->glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    core->glClear(GL_COLOR_BUFFER_BIT);

    core->glActiveTexture(GL_TEXTURE0);
    core->glBindTexture(GL_TEXTURE_2D, texture1);
    core->glActiveTexture(GL_TEXTURE1);
    core->glBindTexture(GL_TEXTURE_2D, texture2);
    core->glBindVertexArray(VAO[0]);
    //core->glDrawArrays(GL_LINE_LOOP, 0, 3);
    core->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

}


